package com.zhieasy.xpuapi.core;

import cn.hutool.core.util.ObjectUtil;
import com.zhieasy.common.exception.Asserts;
import com.zhieasy.service.CheckCodeService;
import com.zhieasy.xpuapi.entity.StudentPojo;
import com.zhieasy.xpuapi.contant.SpiderConstant;
import com.zhieasy.xpuapi.entity.TmpSpiderData;
import okhttp3.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URL;

/**
 * 对接学校教务处的api
 * @author 风亦未止
 * @date 2021/11/3 14:44
 */
@Component
public class XpuApi {
    @Autowired
    private CheckCodeService checkCodeservice;

    private  OkHttpClient okHttpClient = new OkHttpClient();
//    private static final ConcurrentHashMap<String, TmpSpiderData> tmpSpiderKV = new ConcurrentHashMap<>();
    /**
     * 获取验证码 URL
     * @return URL
     */
    public String getCheckCodeUrl(String stuId){
        //模拟打开链接
        Request request = new Request.Builder().get().url(SpiderConstant.BASE_URL).build();
        try {
            Response execute = okHttpClient.newCall(request).execute();
            //获取新的链接，后面要用于生成__VIEWSTATE
            String newUrl = execute.request().url().toString();
            //获取sessionCode，地址栏上的
            String sessionCode = newUrl.substring(23, newUrl.length() - 15);
            String checkCodeUrl = String.format("%s/(%s)/CheckCode.aspx", SpiderConstant.BASE_URL, sessionCode);
            //储存登录需要的临时数据
//            tmpSpiderKV.put(stuId,new TmpSpiderData(sessionCode,newUrl,""));
            checkCodeservice.put(stuId,new TmpSpiderData(sessionCode,newUrl,""));
            execute.close();
            return checkCodeUrl;
        } catch (IOException e){
            e.printStackTrace();
        }
        return "ERROR!";
    }

    /**
     * 此方法用于同步获取用户学生信息 + 当年学年的课表信息
     * @param stuId 学生学号
     * @param password 教务系统密码
     * @param checkCode 验证码
     */
    public StudentPojo go(String stuId, String password, String checkCode) throws Exception {

        TmpSpiderData tmpSpiderData = (TmpSpiderData) checkCodeservice.get(stuId);
        if(tmpSpiderData == null) {
            Asserts.fail("请重新获取验证码！");
        }
        Document document = Jsoup.parse(new URL(tmpSpiderData.getNewUrl()), 5000);
        String __VIEWSTATE = document.select("form#form1 > input").first().attr("value");
        // 更新__VIEWSTATE
        tmpSpiderData.set__VIEWSTATE(__VIEWSTATE);
        checkCodeservice.put(stuId, tmpSpiderData);
        RequestBody requestBody = new FormBody.Builder()
                .add("__VIEWSTATE", __VIEWSTATE)
                .add("txtUserName", stuId)
                .add("TextBox2", password)
                .add("txtSecretCode", checkCode)
                .add("RadioButtonList1","(unable to decode value)")
                .add("Button1", "")
                .add("lbLanguage", "")
                .add("hidPdrs", "")
                .add("hidsc", "")
                .build();
        String loginUrl = String.format("%s/(%s)/default2.aspx", SpiderConstant.BASE_URL, tmpSpiderData.getSessionCode());
        Request request = new Request.Builder().post(requestBody).url(loginUrl).build();
        Response response = null;
        try {
            response = okHttpClient.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        String studentMainUrl = response.request().url().toString();
        request = new Request.Builder().get().url(studentMainUrl).build();
        Response execute = okHttpClient.newCall(request).execute();

        assert execute.body() != null;
        String studentMainBody = execute.body().string();
        Document mainDoc = Jsoup.parse(studentMainBody);

        if("欢迎使用正方教务管理系统！请登录".equals(mainDoc.select("title").first().text())){
           //登录失败返回空
            checkCodeservice.remove(stuId);
            response.close();
            return null;
        }
        StudentPojo studentPojoInfo = getStudentInfo(mainDoc, tmpSpiderData.getSessionCode(), studentMainUrl);
        //获取成功后删除临时数据
        checkCodeservice.remove(stuId);
        response.close();
        return studentPojoInfo;
    }


    /**
     * 获取学生用户信息
     */
    private  StudentPojo getStudentInfo(Document mainDoc, String sessionCode, String studentMainUrl) throws IOException {
        String info = null;
        try {
            info = mainDoc.select("[onclick=GetMc('学生信息维护');]").first().attr("href");
        } catch (NullPointerException e) {
            Asserts.fail("教务处系统出错，获取信息失败！");
        }
        String infoUrl = String.format("%s/(%s)/%s",SpiderConstant.BASE_URL, sessionCode, info);
        Request request = new Request.Builder()
                .get()
                .addHeader("Referer", studentMainUrl)
                .addHeader("Connection", "keep-alive")
                .addHeader("Accept-Encoding", "gzip, deflate")
                .addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
                .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36")
                .url(infoUrl).build();
        Response execute = okHttpClient.newCall(request).execute();
        assert execute.body() != null;
        String StudentInfoBody = new String(execute.body().bytes(), "GB2312");

        Document studentInfoBody = Jsoup.parse(StudentInfoBody);
        StudentPojo stu = new StudentPojo(studentInfoBody.select("[id=xh]").first().text(),
                studentInfoBody.select("[id=xm]").first().text(),
                studentInfoBody.select("[id=xy]").first().text(),
                studentInfoBody.select("[id=zy]").first().text(),
                studentInfoBody.select("[id=xzb]").first().text());
        return stu;
    }

}
